package cn.zzf.algs.note.base.collection.v2;

import cn.zzf.algs.note.base.struct.Node;

import java.util.Iterator;

/**
 * 使用单向链表实现的队列
 * @author GaoFeng2017
 * @date 2020/6/12 13:48
 */
public class LinkedQueue<T> implements Iterable<T> {

    /**
     * 尾部结点
     */
    private Node<T> last;

    /** 首节点 */
    private Node<T> first;

    /**
     * 队列中的元素总数量
     */
    private int size;

    /**
     * 将一个元素添加到队尾
     */
    public void enqueue(T element) {
        if (this.first == null) {
            this.last = new Node<>(element, null);
            this.first = this.last;
        } else {
            // 核心思想： 给火车增加火车车厢，新的车厢直接加到屁股后面，尾部信息直接设置为新的车厢。
            // 过程：将last的next指向新的结点，此时新的结点就是最新的last，所以只需要将last指向的新的结点即可。
            Node<T> oldLast = this.last;
            this.last = new Node<>(element, null);
            oldLast.setNext(this.last);
        }

        this.size++;
    }

    /** 删除并返回队尾的元素 */
    public T dequeue() {

        if (this.first == null) {
            this.last = null;
            return null;
        }

        T value = this.first.getValue();
        this.first = this.first.getNext();
        this.size--;

        return value;
    }

    public int size() {
        return this.size;
    }
    public void printState() {
        System.out.println("last is " + this.last + ", first is " + this.first);
    }

    /** 迭代器 */
    @Override
    public Iterator<T> iterator() {

        return new Iterator<T>() {

            private Node<T> currentNode = first;

            @Override
            public boolean hasNext() {
                return currentNode != null;
            }

            @Override
            public T next() {
                T element = currentNode.getValue();
                currentNode = currentNode.getNext();
                return element;
            }

        };
    }

    public boolean isEmpty() {
        return this.size == 0;
    }


    @Override
    public String toString() {

        if (this.size == 0) {
            return "[]";
        }

        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (T t : this) {
            sb.append(t.toString()).append(", ");
        }

        sb.delete(sb.length() - 2, sb.length());

        sb.append("]");

        return sb.toString();

    }
}

